/*
 * @Author: ls
 * @Date: 2020-09-01 15:44:33
 * @LastEditTime: 2020-09-16 14:23:18
 * @LastEditors: Please set LastEditors
 * @Description: 游戏导演类
 * @FilePath: \snake\assets\gameController.js
 */

var noneColor = new cc.color(120, 120, 120, 255);
var foodColor = new cc.color(254, 168, 23, 255);
var snakeColor = new cc.color(243, 60, 66, 255);

cc.Class({
    extends: cc.Component,

    properties: {
        // 棋盘
        node_grid: cc.Node,
        // 分数
        lab_score: cc.Label,
        // 最好分数
        lab_best: cc.Label,

        // 开始
        node_start: cc.Node,
        // 新人引导
        node_guide: cc.Node,
        // 结束
        node_over: cc.Node,

        // 基础类
        cellPrefab: cc.Prefab,

        // 移动速度
        mSpeed: 5,
        // 列数
        colCount: 30,
        // 行数
        rowCount: 30,
    },

    onLoad() {
        // 初始化方向
        // 静止、上、下、左、右
        // (0,0)、(0,1)、(0,-1)、(-1,0)、(1,0)
        this._direction = { x: 0, y: 0 };
        // 初始化细胞大小
        this._cellSize = { x: 10, y: 10 };

        this._map = [];
        this.initCellPool();
        this.onCreateMap();
        // 显示开始游戏界面
        this.showStartGame();
    },

    /**
     * 初始化细胞对象池
     */
    initCellPool() {
        this.cellPool = new cc.NodePool();
        let initCount = this.rowCount * this.colCount;
        for (let i = 0; i < initCount; i++) {
            let cell = cc.instantiate(this.cellPrefab); // 创建节点
            this.cellPool.put(cell); // 通过 put 接口放入对象池
        }
    },

    /**
     * 创建地图
     */
    onCreateMap() {
        this._map = [];
        let node_bg = this.node_grid.getChildByName('background');
        this._cellSize = { x: node_bg.width / this.rowCount, y: node_bg.height / this.colCount };

        for (var y = 0; y < this.colCount; y++) {
            for (let x = 0; x < this.rowCount; x++) {
                var obj = {};
                obj.x = x;
                obj.y = y;
                obj.node = this.createCell(node_bg, x, y);

                this._map.push(obj);
            }
        }
    },

    /**
     * 从对象池请求对象
     * @param {*} parentNode
     */
    createCell: function (parentNode, x, y) {
        let cell = null;
        if (this.cellPool.size() > 0) {
            // 通过 size 接口判断对象池中是否有空闲的对象
            cell = this.cellPool.get();
        } else {
            // 如果没有空闲对象，也就是对象池中备用对象不够时，我们就用 cc.instantiate 重新创建
            cell = cc.instantiate(this.cellPrefab);
        }

        cell.getComponent('cell').setCellPos(this._cellSize);

        cell.x = this._cellSize.x * x;
        cell.y = this._cellSize.y * y;

        cell.parent = parentNode;
        return cell;
    },

    /**
     * 还原地图
     */
    clearMap() {
        for (let index = 0, length = this._map.length; index < length; index++) {
            this._map[index].node.getComponent('cell').setCellColor(noneColor);
        }
    },

    /**
     * 显示开始界面
     */
    showStartGame() {
        this.node_over.active = false;
        this.node_start.active = true;
    },

    /**
     * 显示结束界面
     */
    showOverGame() {
        this.node_start.active = false;
        this.node_over.active = true;
    },

    /**
     * 游戏开始
     */
    startGame() {
        this.node_guide.active = false;
        this.node_over.active = false;
        this.node_start.active = false;
        this.lab_score.node.active = true;
        this.lab_best.node.active = true;
        this.node_grid.active = true;
        // 是否首次进入界面
        if (!cc.sys.localStorage.getItem('isStart')) {
            this.node_guide.active = true;
        }

        this._score = 0;
        // 更新最高分数
        this.updateBest();

        this._canControl = true;
        this._direction = { x: 1, y: 0 };
        this._snakeGrid = [];
        this._foodGrid = {};

        // 初始化触摸事件
        this.openTouchEvent();

        this.clearMap();
        this.onCreateSnake();
        this.onCreateFood();

        // 开启移动
        this.schedule(this.move, 1 / this.mSpeed);
    },

    /**
     * 更新分数
     */
    updateBest() {
        this._best = cc.sys.localStorage.getItem('best');
        if (this._best) {
            if (this._best < this._score) {
                this._best = this._score;
                cc.sys.localStorage.setItem('best', this._best);
            }
        } else {
            this._best = this._score;
            cc.sys.localStorage.setItem('best', this._best);
        }

        this.lab_best.string = this._best;
    },

    /**
     * 游戏结束
     */
    gameOver() {
        // 是否能控制 蛇改变移动方向
        this._canControl = false;

        this.unschedule(this.move);
        this.closeTouchEvent();
        this.clearMap();
        this.showOverGame();
    },

    /**
     * 创建蛇
     */
    onCreateSnake() {
        let x = ~~(Math.random() * this.rowCount);
        let y = ~~(Math.random() * this.colCount);

        for (let index = 0, length = this._map.length; index < length; index++) {
            if (this._map[index].x === x && this._map[index].y === y) {
                this._map[index].node.getComponent('cell').setCellColor(snakeColor);
                this._snakeGrid.push(this._map[index]);
            }
        }
    },

    /**
     * 创建食物
     */
    onCreateFood() {
        if (this._map.length !== this._snakeGrid.length) {
            let r = ~~(Math.random() * (this._map.length - this._snakeGrid.length));

            let subGrid = [];
            for (let i = 0; i < this._map.length; i++) {
                subGrid.push(this._map[i]);
            }

            for (let m = 0; m < subGrid.length; m++) {
                for (let n = 0; n < this._snakeGrid.length; n++) {
                    if (subGrid[m].x === this._snakeGrid[n].x && subGrid[m].y === this._snakeGrid[n].y) {
                        subGrid.splice(m, 1);
                        if (m > 0) {
                            m--;
                        }
                    }
                }
            }

            for (let index = 0; index < subGrid.length; index++) {
                if (index === r) {
                    this._foodGrid = subGrid[index];
                    this._foodGrid.node.getComponent('cell').setCellColor(foodColor);

                    // 增加分数
                    this._score++;
                    this.lab_score.string = this._score;
                }
            }
        }
    },

    /**
     * 打开触摸
     */
    openTouchEvent() {
        var self = this;
        this.node.on(
            cc.Node.EventType.TOUCH_START,
            function (touch) {
                if (self._canControl) {
                    self._canControl = false;
                    let touchPos = self.node.convertToNodeSpaceAR(touch.getLocation());
                    self._direction = self.getTouchDirection(touchPos);

                    this.scheduleOnce(function () {
                        self._canControl = true;
                    }, 1 / this.mSpeed);
                }
            },
            this
        );
    },

    /**
     * 关闭触摸
     */
    closeTouchEvent() {
        this.node.off(cc.Node.EventType.TOUCH_START, this);
    },

    /**
     * 获取选择的方向
     * @param {* 触摸位置} touchPos
     */
    getTouchDirection(touchPos) {
        // 获取向量长度
        function getABS(pos) {
            return Math.sqrt(pos.x * pos.x + pos.y * pos.y);
        }
        // 获取横向 方向
        function getLandscape(touchPos) {
            if (touchPos.x > 0) {
                cc.log('更改为 向 右 移动');
                return { x: 1, y: 0 };
            } else {
                cc.log('更改为 向 左 移动');
                return { x: -1, y: 0 };
            }
        }
        // 获取竖向 方向
        function getPortrait(touchPos) {
            if (touchPos.y > 0) {
                cc.log('更改为 向 上 移动');
                return { x: 0, y: 1 };
            } else {
                cc.log('更改为 向 下 移动');
                return { x: 0, y: -1 };
            }
        }

        if (getABS(this._direction) === 1) {
            cc.log('蛇 正在移动');
            if (this._direction.y === 1) {
                cc.log('蛇 正在向 上 移动');
                return getLandscape(touchPos);
            } else if (this._direction.y === -1) {
                cc.log('蛇 正在向 下 移动');
                return getLandscape(touchPos);
            } else if (this._direction.x === -1) {
                cc.log('蛇 正在向 左 移动');
                return getPortrait(touchPos);
            } else if (this._direction.x === 1) {
                cc.log('蛇 正在向 右 移动');
                return getPortrait(touchPos);
            }
        } else {
            cc.log('蛇 未开始 或 停止了移动。此时修改方向无效！');
        }
    },

    /**
     * 移动
     */
    move() {
        let nextGrid = {};
        nextGrid.x = this._snakeGrid[this._snakeGrid.length - 1].x + this._direction.x;
        nextGrid.y = this._snakeGrid[this._snakeGrid.length - 1].y + this._direction.y;

        if (this._direction.x === 1) {
            // 向右
            if (nextGrid.x > this.colCount - 1) {
                nextGrid.x = 0;
            }
        } else if (this._direction.x === -1) {
            // 向左
            if (nextGrid.x < 0) {
                nextGrid.x = this.colCount - 1;
            }
        } else if (this._direction.y === 1) {
            // 向上
            if (nextGrid.y > this.rowCount - 1) {
                nextGrid.y = 0;
            }
        } else if (this._direction.y === -1) {
            // 向下
            if (nextGrid.y < 0) {
                nextGrid.y = this.rowCount - 1;
            }
        }

        for (let m = 0, l = this._map.length; m < l; m++) {
            if (this._map[m].x === nextGrid.x && this._map[m].y === nextGrid.y) {
                nextGrid = this._map[m];
            }
        }

        for (let n = 0, length = this._snakeGrid.length; n < length; n++) {
            if (nextGrid.x === this._snakeGrid[n].x && nextGrid.y === this._snakeGrid[n].y) {
                this.gameOver();
                // return false;
            }
        }

        nextGrid.node.getComponent('cell').setCellColor(snakeColor);
        this._snakeGrid.push(nextGrid);

        if (nextGrid.x === this._foodGrid.x && nextGrid.y === this._foodGrid.y) {
            this.onCreateFood();
        } else {
            let startGrid = this._snakeGrid.shift();
            startGrid.node.getComponent('cell').setCellColor(noneColor);
        }
    },
});
